home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Special 21 / AMIGAplus Sonderheft 21 (1999)(ICP)(DE)[!].iso / PublicDomain / Spiele / scott / source / Source.lha / SCOTT_A.C < prev    next >
C/C++ Source or Header  |  1999-04-13  |  12KB  |  645 lines

  1. /*
  2.  *  ScottFree Revision 1.14b
  3.  *
  4.  *
  5.  *  This program is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU General Public License
  7.  *  as published by the Free Software Foundation; either version
  8.  *  2 of the License, or (at your option) any later version.
  9.  *
  10.  *
  11.  *  You must have an ANSI C compiler to build this program.
  12.  *
  13.  *  ===================================================================
  14.  *
  15.  *  Version History AMIGA:
  16.  *  Ver ,     Date,     Author, Comment
  17.  *  -------------------------------------------------------------------
  18.  *  1.0 , 28/07/96, Andreas Aumayr, First public release
  19.  *  1.1 , 30/08/96, Andreas Aumayr, Minor changes for new amiga.c
  20.  *  ___________________________________________________________________
  21.  */
  22.  
  23.  
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <stdlib.h>
  27. #include <ctype.h>
  28. #include <stdarg.h>
  29. #include <time.h>
  30. //#include <math.h>
  31.  
  32. #include "Scott.h"
  33. #include "ansi.c"
  34. #include "protos.h"
  35. #include "amiga6.c"
  36.  
  37. int OutputPos=0;
  38.  
  39. void Fatal(char *x)
  40. {
  41.     sprintf(str_buf,"\n\n%s!\n",x);
  42.     WriteCON(str_buf);
  43.     Delay(200);
  44.     close_all();
  45.     exit(1);
  46. }
  47.  
  48. void put_choice(void)
  49. {
  50.     if (RESTART) {
  51.         OutBuf("\nDo you want to (R)estore, re(S)tart or (E)xit the game? ");
  52.         Speak("Do you want to R 4 restore, S 4 restart or E 4 exit the game?");
  53.     }
  54.     else {
  55.         OutBuf("\nDo you want to (R)estore or (E)xit the game? ");
  56.         Speak("Do you want to R 4 restore or E 4 exit the game?");
  57.     }
  58.     cursor(TRUE);
  59. }
  60.  
  61. int RandomPercent(int n)
  62. {
  63.     unsigned int rv=rand()<<6;
  64.     rv=rv%100;
  65.     if(rv<n)
  66.         return(1);
  67.     return(0);
  68. }
  69.  
  70. int CountCarried()
  71. {
  72.     int ct=0;
  73.     int n=0;
  74.     while(ct<=GameHeader.NumItems)
  75.     {
  76.         if(Items[ct].Location==CARRIED)
  77.             n++;
  78.         ct++;
  79.     }
  80.     return(n);
  81. }
  82.  
  83. char *MapSynonym(char *word)
  84. {
  85.     int n=1;
  86.     char *tp;
  87.     static char lastword[16];   /* Last non synonym */
  88.     while(n<=GameHeader.NumWords)
  89.     {
  90.         tp=Nouns[n];
  91.         if(*tp=='*')
  92.             tp++;
  93.         else
  94.             strcpy(lastword,tp);
  95.         if(Strnicmp(word,tp,GameHeader.WordLength)==0)
  96.             return(lastword);
  97.         n++;
  98.     }
  99.     return(NULL);
  100. }
  101.  
  102. int MatchUpItem(char *text, int loc)
  103. {
  104.     char *word=MapSynonym(text);
  105.     int ct=0;
  106.  
  107.         if(word==NULL)
  108.         word=text;
  109.  
  110.         while(ct<=GameHeader.NumItems)
  111.     {
  112.         if(Items[ct].AutoGet && Items[ct].Location==loc &&
  113.             Strnicmp(Items[ct].AutoGet,word,GameHeader.WordLength)==0)
  114.             return(ct);
  115.         ct++;
  116.     }
  117.     return(-1);
  118. }
  119.  
  120. char *ReadString(FILE *f)
  121. {
  122.     char tmp[1024];
  123.     char *t;
  124.     int c,nc;
  125.     int ct=0;
  126. oops:   do
  127.     {
  128.         c=fgetc(f);
  129.     }
  130.     while(c!=EOF && isspace(c));
  131.     if(c!='"')
  132.     {
  133.         Fatal("Initial quote expected");
  134.     }
  135.     do
  136.     {
  137.         c=fgetc(f);
  138.         if(c==EOF)
  139.             Fatal("EOF in string");
  140.         if(c=='"')
  141.         {
  142.             nc=fgetc(f);
  143.             if(nc!='"')
  144.             {
  145.                 ungetc(nc,f);
  146.                 break;
  147.             }
  148.         }
  149.         if(c==0x60)
  150.             c='"'; /* pdd */
  151.         tmp[ct++]=c;
  152.     }
  153.     while(1);
  154.     tmp[ct]=0;
  155.     t=MemAlloc(ct+1);
  156.     memcpy(t,tmp,ct+1);
  157.     return(t);
  158. }
  159.  
  160. void NextLine()
  161. {
  162.     WriteCON("\n");
  163.     OutputPos = 0;
  164.     //OutReset();
  165. }
  166.  
  167. void Look()
  168. {
  169.     static char *ExitNames[6]=
  170.     {
  171.         "North","South","East","West","Up","Down"
  172.     };
  173.     Room *r;
  174.     int ct,f;
  175.     int pos;
  176.  
  177.     CON_handle = env_hdl;
  178.     clrscr();
  179.  
  180.     if ((BitFlags&(1L<<DARKBIT)) && Items[LIGHT_SOURCE].Location!= CARRIED
  181.        && Items[LIGHT_SOURCE].Location!= MyLoc) {
  182.         if (Options&YOUARE) {
  183.             WriteCON("You can't see. It is too dark!\n");
  184.             Speak("You can't see. It is too dark!");
  185.         }
  186.         else {
  187.             WriteCON("I can't see. It is too dark!\n");
  188.             Speak("I can't see. It is too dark!");
  189.         }
  190.         if (Options & TRS80_STYLE) WriteCON(TRS80_LINE);
  191.  
  192.         if (GFX && last_pic) Open_Pic(0,PIC);
  193.  
  194.         CON_handle = act_hdl;
  195.         return;
  196.     }
  197.  
  198.     r=&Rooms[MyLoc];
  199.     if(*r->Text=='*') {
  200.         sprintf(str_buf,"%s\n",r->Text+1);
  201.         OutBuf(str_buf);
  202.         Speak(str_buf);
  203.     }
  204.     else
  205.     {
  206.         if(Options&YOUARE) {
  207.             sprintf(str_buf,"You are %s\n",r->Text);
  208.             OutBuf(str_buf);
  209.             Speak(str_buf);
  210.         }
  211.         else {
  212.             sprintf(str_buf,"I'm in a %s\n",r->Text);
  213.             OutBuf(str_buf);
  214.             Speak(str_buf);
  215.         }
  216.     }
  217.     ct=0;
  218.     f=0;
  219.     WriteCON("\nObvious exits: ");
  220.     Speak("Obvious exits are:");
  221.     while(ct<6)
  222.     {
  223.         if(r->Exits[ct]!=0)
  224.         {
  225.             if(f==0)
  226.                 f=1;
  227.             else
  228.                 WriteCON(", ");
  229.             WriteCON(ExitNames[ct]);
  230.             Speak(ExitNames[ct]);
  231.         }
  232.         ct++;
  233.     }
  234.     if(f==0) {
  235.         WriteCON("none");
  236.         Speak("none");
  237.     }
  238.     WriteCON(".\n");
  239.     ct=0;
  240.     f=0;
  241.     pos=0;
  242.     while(ct<=GameHeader.NumItems)
  243.     {
  244.         if(Items[ct].Location==MyLoc)
  245.         {
  246.             //printf("Item %d is in Room\n",ct);
  247.             if(f==0)
  248.             {
  249.                 if(Options&YOUARE) {
  250.                     WriteCON("\nYou can also see: ");
  251.                     Speak("You can also see:");
  252.                 }
  253.                 else {
  254.                     WriteCON("\nI can also see: ");
  255.                     Speak("I can also see:");
  256.                 }
  257.                 pos=16;
  258.                 f++;
  259.             }
  260.             else if (!(Options & TRS80_STYLE))
  261.             {
  262.                 WriteCON(" - ");
  263.                 pos+=3;
  264.             }
  265.             if(pos+strlen(Items[ct].Text)>(Width-10))
  266.             {
  267.                 pos=0;
  268.                 WriteCON("\n");
  269.             }
  270.             WriteCON(Items[ct].Text);
  271.             Speak(Items[ct].Text);
  272.             pos += strlen(Items[ct].Text);
  273.             if (Options & TRS80_STYLE)
  274.             {
  275.                 WriteCON(". ");
  276.                 pos+=2;
  277.             }
  278.         }
  279.         ct++;
  280.     }
  281.     if (Options & TRS80_STYLE) WriteCON(TRS80_LINE);
  282.     if (GFX) Handle_Pic(MyLoc);
  283.     CON_handle = act_hdl;
  284. }
  285.  
  286. void LoadDatabase(FILE *f, int loud)
  287. {
  288.     char buf[32];
  289.     int ni,na,nw,nr,mc,pr,tr,wl,lt,mn,trm;
  290.     int ct;
  291.     short lo;
  292.     Action *ap;
  293.     Room *rp;
  294.     Item *ip;
  295. /* Load the header */
  296.  
  297.     if(fscanf(f,"%*d %d %d %d %d %d %d %d %d %d %d %d",
  298.         &ni,&na,&nw,&nr,&mc,&pr,&tr,&wl,<,&mn,&trm,&ct)<10)
  299.         Fatal("Invalid database(bad header)");
  300.     GameHeader.NumItems=ni;
  301.     Items=(Item *)MemAlloc(sizeof(Item)*(ni+1));
  302.     GameHeader.NumActions=na;
  303.     Actions=(Action *)MemAlloc(sizeof(Action)*(na+1));
  304.     GameHeader.NumWords=nw;
  305.     GameHeader.WordLength=wl;
  306.     Verbs=(char **)MemAlloc(sizeof(char *)*(nw+1));
  307.     Nouns=(char **)MemAlloc(sizeof(char *)*(nw+1));
  308.     GameHeader.NumRooms=nr;
  309.     Rooms=(Room *)MemAlloc(sizeof(Room)*(nr+1));
  310.     GameHeader.MaxCarry=mc;
  311.     GameHeader.PlayerRoom=pr;
  312.     GameHeader.Treasures=tr;
  313.     GameHeader.LightTime=lt;
  314.     LightRefill=lt;
  315.     GameHeader.NumMessages=mn;
  316.     Messages=(char **)MemAlloc(sizeof(char *)*(mn+1));
  317.     GameHeader.TreasureRoom=trm;
  318.  
  319. /* Load the actions */
  320.  
  321.     ct=0;
  322.     ap=Actions;
  323.     if(loud)
  324.         printf("Reading %d actions.\n",na);
  325.     sprintf(buf,"Actions:   %d\n",na);
  326.     strcat(GameInfoStr,buf);
  327.     while(ct<na+1)
  328.     {
  329.         if(fscanf(f,"%hd %hd %hd %hd %hd %hd %hd %hd",
  330.             &ap->Vocab,
  331.             &ap->Condition[0],
  332.             &ap->Condition[1],
  333.             &ap->Condition[2],
  334.             &ap->Condition[3],
  335.             &ap->Condition[4],
  336.             &ap->Action[0],
  337.             &ap->Action[1])!=8)
  338.         {
  339.             printf("Bad action line (%d)\n",ct);
  340.             exit(1);
  341.         }
  342.         ap++;
  343.         ct++;
  344.     }
  345.     ct=0;
  346.     if(loud)
  347.         printf("Reading %d word pairs.\n",nw);
  348.     sprintf(buf,"Word Pairs: %d\n",nw);
  349.     strcat(GameInfoStr,buf);
  350.     while(ct<nw+1)
  351.     {
  352.         Verbs[ct]=ReadString(f);
  353.         Nouns[ct]=ReadString(f);
  354.         ct++;
  355.     }
  356.     ct=0;
  357.     rp=Rooms;
  358.     if(loud)
  359.         printf("Reading %d rooms.\n",nr);
  360.     sprintf(buf,"Rooms:      %d\n",nr);
  361.     strcat(GameInfoStr,buf);
  362.     while(ct<nr+1)
  363.     {
  364.         fscanf(f,"%hd %hd %hd %hd %hd %hd",
  365.             &rp->Exits[0],&rp->Exits[1],&rp->Exits[2],
  366.             &rp->Exits[3],&rp->Exits[4],&rp->Exits[5]);
  367.         rp->Text=ReadString(f);
  368.         ct++;
  369.         rp++;
  370.     }
  371.     ct=0;
  372.     if(loud)
  373.         printf("Reading %d messages.\n",mn);
  374.     sprintf(buf,"Messages:   %d\n",mn);
  375.     strcat(GameInfoStr,buf);
  376.     while(ct<mn+1)
  377.     {
  378.         Messages[ct]=ReadString(f);
  379.         ct++;
  380.     }
  381.     ct=0;
  382.     if(loud)
  383.         printf("Reading %d items.\n",ni);
  384.     sprintf(buf,"Items:      %d\n",ni);
  385.     strcat(GameInfoStr,buf);
  386.     ip=Items;
  387.     while(ct<ni+1)
  388.     {
  389.         ip->Text=ReadString(f);
  390.         ip->AutoGet=strchr(ip->Text,'/');
  391.         /* Some games use // to mean no auto get/drop word! */
  392.         if(ip->AutoGet && strcmp(ip->AutoGet,"//") && strcmp(ip->AutoGet,"/*"))
  393.         {
  394.             char *t;
  395.             *ip->AutoGet++=0;
  396.             t=strchr(ip->AutoGet,'/');
  397.             if(t!=NULL)
  398.                 *t=0;
  399.         }
  400.         fscanf(f,"%hd",&lo);
  401.         ip->Location=(unsigned char)lo;
  402.         ip->InitialLoc=ip->Location;
  403.         ip++;
  404.         ct++;
  405.     }
  406.     ct=0;
  407.     /* Discard Comment Strings */
  408.     while(ct<na+1)
  409.     {
  410.         free(ReadString(f));
  411.         ct++;
  412.     }
  413.     fscanf(f,"%d",&ct);
  414.     if(loud)
  415.         printf("Version %d.%02d of Adventure ",ct/100,ct%100);
  416.     sprintf(buf,"Version:  %d.%02d\n",ct/100,ct%100);
  417.     strcat(GameInfoStr,buf);
  418.     fscanf(f,"%d",&ct);
  419.     if(loud)
  420.         printf("%d.\nLoad Complete.\n\n",ct);
  421.     sprintf(buf,"Game Nr.:   %2d",ct);
  422.     strcat(GameInfoStr,buf);
  423. }
  424.  
  425. void OutReset()
  426. {
  427.     OutputPos=0;
  428.     gotoxy(1,BottomHeight);
  429.     clreol();
  430. }
  431.  
  432. void OutBuf(char *buffer)
  433. {
  434.     char word[80];
  435.     int wp,len;
  436.  
  437.     len = strlen(buffer);
  438.     while(*buffer)
  439.     {
  440.         if(OutputPos==0)
  441.         {
  442.             while(*buffer && isspace(*buffer))
  443.             {
  444.                 if (*buffer=='\n') NextLine();
  445.                 buffer++;
  446.             }
  447.         }
  448.         if(*buffer==0) {
  449.             return;
  450.         }
  451.         wp=0;
  452.         while(*buffer && ((!isspace(*buffer)) || (*(buffer-1) == '*') || (*(buffer+1) == '*')))
  453.         {
  454.             word[wp++]=*buffer++;
  455.         }
  456.         word[wp]=0;
  457.  
  458.         //printf("Word '%s' at %d\n",word,OutputPos);
  459.  
  460.         if (LINEWRAP) {
  461.             if ((OutputPos + strlen(word) > Width - 2)  && (*word != '.')) NextLine();
  462.             OutputPos += strlen(word);
  463.         }
  464.         else {
  465.             if (((OutputPos + strlen(word) > Width - 2)  && (*word != '.') && (len <= Width)) || (OutputPos == Width)) NextLine();
  466.             OutputPos += strlen(word);
  467.             if (OutputPos >= Width) OutputPos -= Width;
  468.         }
  469.  
  470.         WriteCON(word);
  471.         
  472.         if(*buffer==0) {
  473.             return;
  474.         }
  475.  
  476.         if (*buffer=='\n') NextLine();
  477.         else
  478.         {
  479.             OutputPos++;
  480.             if(OutputPos < (Width-1))
  481.                 WriteCON(" ");
  482.         }
  483.         buffer++;
  484.     }
  485. }
  486.  
  487. void Output(char *a)
  488. {
  489.     char block[512];
  490.     strcpy(block,a);
  491.     OutBuf(block);
  492. }
  493.  
  494. void OutputNumber(int a)
  495. {
  496.     char buf[16];
  497.     sprintf(buf,"%d ",a);
  498.     OutBuf(buf);
  499. }
  500.  
  501. void GetInput(int *vb, int *no)
  502. {
  503.     char buf[256];
  504.     char verb[10],noun[10];
  505.     int vc,nc;
  506.     int num;
  507.  
  508.     do
  509.     {
  510.         do
  511.         {
  512.             Output("\nTell me what to do ? ");
  513.             Speak("Tell me what to do?");
  514.             cursor(TRUE);
  515.             LineInput2(buf);
  516.             Speak(buf);
  517.             cursor(FALSE);
  518.             OutReset();
  519.             num=sscanf(buf,"%9s %9s",verb,noun);
  520.         }
  521.         while(num==0||*buf=='\n'||*buf==0);
  522.         //printf("%d, %s, %s\n",num,verb,noun);
  523.         if(num==1)
  524.             *noun=0;
  525.         if(*noun==0 && strlen(verb)==1)
  526.         {
  527.             switch(isupper(*verb)?tolower(*verb):*verb)
  528.             {
  529.                 case 'n':strcpy(verb,"NORTH");break;
  530.                 case 'e':strcpy(verb,"EAST");break;
  531.                 case 's':strcpy(verb,"SOUTH");break;
  532.                 case 'w':strcpy(verb,"WEST");break;
  533.                 case 'u':strcpy(verb,"UP");break;
  534.                 case 'd':strcpy(verb,"DOWN");break;
  535.                 /* Brian Howarth interpreter also supports this */
  536.                 case 'i':strcpy(verb,"INVENTORY");break;
  537.                 /* AMIGA interpreter extension */
  538.                 case 'l':strcpy(verb,"LOOK");break;
  539.             }
  540.         }
  541.         nc=WhichWord(verb,Nouns);
  542.         /* The Scott Adams system has a hack to avoid typing 'go' */
  543.         if(nc>=1 && nc <=6)
  544.         {
  545.             vc=1;
  546.         }
  547.         else
  548.         {
  549.             vc=WhichWord(verb,Verbs);
  550.             nc=WhichWord(noun,Nouns);
  551.         }
  552.         *vb=vc;
  553.         *no=nc;
  554.         if(vc==-1)
  555.         {
  556.             Output("\"");
  557.             Output(verb);
  558.             Speak(verb);
  559.             Output("\" is a word I don't know...sorry!\n");
  560.             Speak("is a word I don't know. Sorry!");
  561.         }
  562.     }
  563.     while(vc==-1);
  564.     strcpy(NounText,noun);  /* Needed by GET/DROP hack */
  565. }
  566.  
  567. void SaveGame(void)
  568. {
  569.     FILE *f;
  570.  
  571.     if (Open_ASL(save_game,save_dir,1) == FALSE) {
  572.         Output("Save game canceled.\n");
  573.         Speak("Save game canceled.");
  574.         return;
  575.     }
  576.     Make_FFP(save_game,save_dir);
  577.     f=fopen(FFP,"w");
  578.     if(f==NULL)
  579.     {
  580.         sprintf(str_buf,"Unable to create save file '%s'.\n",FFP);
  581.         Output(str_buf);
  582.         Speak("Unable to create save file.");
  583.         return;
  584.     }
  585.     SaveBody(f);
  586.     sprintf(str_buf,"Saved '%s'.\n",FFP);
  587.     Output(str_buf);
  588.     Speak("Game saved.");
  589.     return;
  590. }
  591.  
  592. BOOL LoadGame(char *name)
  593. {
  594.     FILE *f=fopen(name,"r");
  595.  
  596.     if(f==NULL)
  597.     {
  598.         sprintf(str_buf,"Unable to restore game '%s'.\n\n",name);
  599.         Output(str_buf);
  600.         Speak("Unable to restore game.");
  601.         return(TRUE);
  602.     }
  603.     LoadBody(f);
  604.     sprintf(str_buf,"Restored '%s'.\n",name);
  605.     Output(str_buf);
  606.     Speak("Game restored.");
  607.     return(FALSE);
  608. }
  609.  
  610. BOOL RestoreGame()
  611. {
  612.     if (Open_ASL(save_game,save_dir,0) == FALSE) return(TRUE);
  613.     Make_FFP(save_game,save_dir);
  614.     return(LoadGame(FFP));
  615. }
  616.  
  617. int WhichWord(char *word, char **list)
  618. {
  619.     int n=1;
  620.     int ne=1;
  621.     char *tp;
  622.  
  623.     /* quick & dirty workaround for missing feature 'RESTORE'
  624.        no more need for quit/restart game. */
  625.     if(Strnicmp(word,"!RESTORE",GameHeader.WordLength)==0) {
  626.         RestoreGame();
  627.         strcpy(word,"LOOK");
  628.         Redraw = 1;
  629.     }
  630.  
  631.     while(ne<=GameHeader.NumWords)
  632.     {
  633.         tp=list[ne];
  634.         if(*tp=='*')
  635.             tp++;
  636.         else
  637.             n=ne;
  638.         if(Strnicmp(word,tp,GameHeader.WordLength)==0)
  639.             return(n);
  640.         ne++;
  641.     }
  642.     return(-1);
  643. }
  644.  
  645.